package com.probox.common.entity.service.platfom.impl;


import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.tea.TeaException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import com.google.code.kaptcha.Producer;
import com.google.gson.Gson;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20190711.models.SendStatus;
import com.probox.common.core.constant.CachePrefix;
import com.probox.common.core.enums.DataStatus;
import com.probox.common.core.enums.SmsConfgiType;
import com.probox.common.core.exception.BaseException;
import cn.hutool.core.date.DateUtil;
import com.probox.common.core.exception.PlatformException;
import com.probox.common.core.utils.SecurityUtils;
import com.probox.common.core.utils.StringUtils;
import com.probox.common.redis.service.RedisService;
import com.probox.platform.api.domain.PlatformSmsApi;
import com.probox.common.entity.domain.platfom.PlatformSendSms;
import com.probox.common.entity.service.platfom.IPlatformSendSmsService;
import feign.AsyncClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.probox.common.entity.mapper.platfom.PlatformSmsConfigMapper;
import com.probox.common.entity.domain.platfom.PlatformSmsConfig;
import com.probox.common.entity.service.platfom.IPlatformSmsConfigService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;


import javax.annotation.Resource;

/**
 * 短信配置Service业务层处理
 *
 *
 * @date 2021-06-22
 */
@Service
@Transactional
public class PlatformSmsConfigServiceImpl extends ServiceImpl<PlatformSmsConfigMapper, PlatformSmsConfig> implements IPlatformSmsConfigService {
    @Autowired
    private PlatformSmsConfigMapper platformSmsConfigMapper;

    @Autowired
    private IPlatformSendSmsService iPlatformSendSmsService;

    @Autowired
    private RedisService redisService;

    @Resource(name = "captchaProduc")
    private Producer captchaProduc;

    private static final Logger logger = LoggerFactory.getLogger(PlatformSmsConfigServiceImpl.class);


    /**
     * 查询短信配置
     *
     * @param configId 短信配置ID
     * @return 短信配置
     */
    @Override
    public PlatformSmsConfig selectPlatformSmsConfigById(Long configId) {
        return this.getById(configId);
    }

    /**
     * 查询短信配置列表
     *
     * @param platformSmsConfig 短信配置
     * @return 短信配置
     */
    @Override
    public List<PlatformSmsConfig> queryList(PlatformSmsConfig platformSmsConfig) {
        Long platformId = SecurityUtils.getPlatformId();
        if (platformId == null) {
            throw new BaseException("当前账号异常");
        }
        platformSmsConfig.setPlatformId(platformId);
        QueryWrapper<PlatformSmsConfig> queryWrapper = Wrappers.query();
        queryWrapper.ne("DATA_STATUS", DataStatus.delete.getKey());
        if (StringUtils.isNotEmpty(String.valueOf(platformSmsConfig.getPlatformId())) && platformSmsConfig.getPlatformId() != null) {
            queryWrapper.eq("platform_id", platformSmsConfig.getPlatformId());
        }
        if (StringUtils.isNotEmpty(String.valueOf(platformSmsConfig.getSmsPlatform())) && platformSmsConfig.getSmsPlatform() != null) {
            queryWrapper.eq("sms_platform", platformSmsConfig.getSmsPlatform());
        }
        if (StringUtils.isNotEmpty(String.valueOf(platformSmsConfig.getSign())) && platformSmsConfig.getSign() != null) {
            queryWrapper.like("sign", platformSmsConfig.getSign());
        }
        if (StringUtils.isNotEmpty(String.valueOf(platformSmsConfig.getDataStatus())) && platformSmsConfig.getDataStatus() != null) {
            queryWrapper.eq("data_status", platformSmsConfig.getDataStatus());
        }
        if (StringUtils.isNotEmpty(String.valueOf(platformSmsConfig.getSmsType())) && platformSmsConfig.getSmsType() != null) {
            queryWrapper.eq("sms_type", platformSmsConfig.getSmsType());
        }
        return platformSmsConfigMapper.selectList(queryWrapper);
    }

    /**
     * 新增短信配置
     *
     * @param platformSmsConfig 短信配置
     * @return 结果
     */
    @Override
    public boolean insertPlatformSmsConfig(PlatformSmsConfig platformSmsConfig) {
        Long userId = SecurityUtils.getUserId();
        String username = SecurityUtils.getUsername();
        Date date = DateUtil.date();
        platformSmsConfig.setPlatformId(SecurityUtils.getPlatformId());
        platformSmsConfig.setCreateUid(userId);
        platformSmsConfig.setCreateName(username);
        platformSmsConfig.setCreateTime(date);
        platformSmsConfig.setUpdateUid(userId);
        platformSmsConfig.setUpdateName(username);
        platformSmsConfig.setUpdateTime(date);
        return this.save(platformSmsConfig);

    }

    /**
     * 修改短信配置
     *
     * @param platformSmsConfig 短信配置
     * @return 结果
     */
    @Override
    public boolean updatePlatformSmsConfig(PlatformSmsConfig platformSmsConfig) {
        platformSmsConfig.setUpdateUid(SecurityUtils.getUserId());
        platformSmsConfig.setUpdateName(SecurityUtils.getUsername());
        platformSmsConfig.setUpdateTime(DateUtil.date());
        return this.updateById(platformSmsConfig);
    }

    /**
     * 批量删除短信配置
     *
     * @param configIds 需要删除的短信配置ID
     * @return 结果
     */
    @Override
    public boolean deletePlatformSmsConfigByIds(Long[] configIds) {
        UpdateWrapper<PlatformSmsConfig> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("CONFIG_ID", Arrays.asList(configIds));
        updateWrapper.set("DATA_STATUS", DataStatus.delete.getKey());
        updateWrapper.set("UPDATE_UID", SecurityUtils.getUserId());
        updateWrapper.set("UPDATE_NAME", SecurityUtils.getUsername());
        updateWrapper.set("UPDATE_TIME", DateUtil.date());
        return this.removeByIds(Arrays.asList(configIds));
    }

    /**
     *  获取验证码
     * @param phone
     * @param ip
     */
    @Override
    public void smsLoginCode(String phone, String ip,Long platformUid){
        String key = CachePrefix.SMS_CODE + phone + "_COUNT";
        if (redisService.incr(key, 60l, TimeUnit.SECONDS) > 1) {
            throw new BaseException("请勿频繁获取验证码");
        }
        key = CachePrefix.SMS_CODE + ip + "_COUNT";
        if (redisService.incr(key, 5l, TimeUnit.MINUTES) > 10) {
            throw new BaseException("请勿频繁获取验证码");
        }
        Assert.hasText(phone, "手机号为空");
        if (!phone.startsWith("86")) {
            phone = new StringBuffer("86").append(phone).toString();
        }
        QueryWrapper<PlatformSmsConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("platform_id", platformUid);
        queryWrapper.eq("sms_type", SmsConfgiType.code.getKey());
        queryWrapper.eq("sms_platform", "腾讯");
        PlatformSmsConfig config = platformSmsConfigMapper.selectOne(queryWrapper);
        if (ObjectUtil.isEmpty(config)) throw new PlatformException("没有找到短信配置信息！");
        Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setEndpoint("sms.tencentcloudapi.com");
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        SmsClient client = new SmsClient(cred, "", clientProfile);
        SendSmsRequest req = new SendSmsRequest();
        String[] phoneNumberSet1 = {phone};
        req.setPhoneNumberSet(phoneNumberSet1);
        final String code = getSmsCode();
        //logger.info("生成的code是:{}",code);
        String[] templateParamSet1 = {code};
        req.setTemplateParamSet(templateParamSet1);
        req.setSmsSdkAppid(config.getSmsSdkAppid());
        req.setTemplateID(config.getTemplateId());
        req.setSign(config.getSign());
        SendSmsResponse resp = null;
        try {
            resp = client.SendSms(req);
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
        SendStatus[] sendStatusSet = resp.getSendStatusSet();
        if(sendStatusSet[0].getCode().equals("LimitExceeded.PhoneNumberDailyLimit")){
            throw new BaseException("每日获取验证码上限！（最多10条）");
        }
        logger.debug("发送短信结果=======>：" + JSON.toJSONString(resp));
        if (resp != null) {
            com.tencentcloudapi.sms.v20190711.models.SendStatus[] status = resp.getSendStatusSet();
            SendStatus statu = null;
            if (status.length > 0) statu = status[0];
            else throw new BaseException("短信发送失败");
            PlatformSendSms platformSendSms = new PlatformSendSms();
            platformSendSms.setPlatformId(platformUid);
            platformSendSms.setIp(ip);
            platformSendSms.setMobile(phone);
            platformSendSms.setSendDate(DateUtil.date());
            platformSendSms.setSmsCode(code);
            platformSendSms.setState("0");
            platformSendSms.setMsg(statu.getMessage());
            iPlatformSendSmsService.insertPlatformSendSms(platformSendSms);
            if (statu.getCode().equalsIgnoreCase("ok")) {
                logger.debug("sms cache key============>" + CachePrefix.SMS_CODE + platformUid + "_" + phone + "  value:" + code);
                redisService.setCacheObject(CachePrefix.SMS_CODE + platformUid + "_" + phone, code, 6l, TimeUnit.MINUTES);
            } else {
                throw new BaseException(statu.getMessage());
            }
        } else {
            throw new BaseException("短信发送失败");
        }
    }

    public com.aliyun.dysmsapi20170525.Client createClient(String keyId,String secret) throws Exception {
        // 工程代码建议使用更安全的无AK方式，凭据配置方式请参见：https://help.aliyun.com/document_detail/378657.html。
        //com.aliyun.credentials.Client credential = new com.aliyun.credentials.Client();
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                .setAccessKeyId(keyId).setAccessKeySecret(secret);
        // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new com.aliyun.dysmsapi20170525.Client(config);
    }

    /**
     *  获取验证码
     * @param phone
     * @param ip
     */
    @Override
    public void smsLoginCodeAlibaba(String phone, String ip,Long platformUid){
        String key = CachePrefix.SMS_CODE + phone + "_COUNT";
        if (redisService.incr(key, 60l, TimeUnit.SECONDS) > 1) {
            throw new BaseException("请勿频繁获取验证码");
        }
        key = CachePrefix.SMS_CODE + ip + "_COUNT";
        if (redisService.incr(key, 5l, TimeUnit.MINUTES) > 10) {
            throw new BaseException("请勿频繁获取验证码");
        }
        Assert.hasText(phone, "手机号为空");
        if (!phone.startsWith("86")) {
            phone = new StringBuffer("86").append(phone).toString();
        }
        QueryWrapper<PlatformSmsConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("platform_id", platformUid);
        queryWrapper.eq("sms_type", SmsConfgiType.code.getKey());
        queryWrapper.eq("sms_platform", "阿里云");
        PlatformSmsConfig config = platformSmsConfigMapper.selectOne(queryWrapper);
        if (ObjectUtil.isEmpty(config)) throw new PlatformException("没有找到短信配置信息！");
        final String code = getSmsCode();
        try{
            com.aliyun.dysmsapi20170525.Client client = createClient(config.getSecretId(),config.getSecretKey());
            com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
                    .setPhoneNumbers(phone)
                    .setSignName(config.getSign())
                    .setTemplateCode(config.getTemplateId())
                    .setTemplateParam("{\"code\":\""+code+"\"}");
            try {
                // 复制代码运行请自行打印 API 的返回值
                com.aliyun.dysmsapi20170525.models.SendSmsResponse response = client.sendSmsWithOptions(sendSmsRequest, new com.aliyun.teautil.models.RuntimeOptions());
                logger.info("发送短信结果=======>：" + JSON.toJSONString(response));
                if (response != null) {
                    String rstCode = response.getBody().getCode();


                    PlatformSendSms platformSendSms = new PlatformSendSms();
                    platformSendSms.setPlatformId(platformUid);
                    platformSendSms.setIp(ip);
                    platformSendSms.setMobile(phone);
                    platformSendSms.setSendDate(DateUtil.date());
                    platformSendSms.setSmsCode(code);
                    platformSendSms.setState("0");
                    platformSendSms.setMsg(response.getBody().getMessage());
                    iPlatformSendSmsService.insertPlatformSendSms(platformSendSms);
                    if (rstCode.equalsIgnoreCase("ok")) {
                        logger.info("sms cache key============>" + CachePrefix.SMS_CODE + platformUid + "_" + phone + "  value:" + code);
                        redisService.setCacheObject(CachePrefix.SMS_CODE + platformUid + "_" + phone, code, 6l, TimeUnit.MINUTES);
                    } else {
                        throw new BaseException(response.getBody().getMessage());
                    }
                } else {
                    throw new BaseException("短信发送失败");
                }
            } catch (TeaException error) {
                // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
                // 错误 message
                System.out.println(error.getMessage());
                // 诊断地址
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
            } catch (Exception _error) {
                TeaException error = new TeaException(_error.getMessage(), _error);
                // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
                // 错误 message
                System.out.println(error.getMessage());
                // 诊断地址
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
            }

        }catch (Exception e){
            e.printStackTrace();
        }




    }

    /**
     *
     * @param smsApi
     */
    @Override
    public void validateSmsCode(PlatformSmsApi smsApi) {

        String code = smsApi.getCode();
        String phone = smsApi.getPhone();
        Long platformId = smsApi.getPlatformId();
        if (!phone.startsWith("86"))
            phone=new StringBuffer("86").append(phone).toString();
        String key = CachePrefix.SMS_CODE+platformId+"_"+phone;
        Object smsCode = redisService.getCacheObject(key);
        if (ObjectUtil.isEmpty(smsCode)) {
            throw new BaseException("短信验证码不正确");
        }
        if(!code.equals(smsCode.toString())){
            throw new BaseException("短信验证码不正确");
        }
        redisService.deleteObject(key);
        iPlatformSendSmsService.validate(platformId, phone, code);


    }


    private String getSmsCode() {
        String text = captchaProduc.createText();
        if (com.alibaba.druid.util.StringUtils.isEmpty(text)) {
            text = String.valueOf((Math.random() * 1000000));
        }
        while (text.length() < 6) {
            text += "0";
        }
        return text;
    }

}
